applied refactored patch from maemo-gtk that replaces the INNER_BORDER
authorMichael Natterer <mitch@gimp.org>
Fri, 10 Mar 2006 10:30:36 +0000 (10:30 +0000)
committerMichael Natterer <mitch@src.gnome.org>
Fri, 10 Mar 2006 10:30:36 +0000 (10:30 +0000)
2006-03-10  Michael Natterer  <mitch@gimp.org>

* gtk/gtkentry.[ch]: applied refactored patch from maemo-gtk that
replaces the INNER_BORDER define by an "inner-border" style
property of type GtkBorder. Additionally, add an "inner-border"
object property plus API which allows to override any theme
border, to allow pixel-perfect positioning of entries for inline
editing. Fixes bug #333922.

* gtk/gtk.symbols: add the new public functions.

ChangeLog
ChangeLog.pre-2-10
gtk/gtk.symbols
gtk/gtkentry.c
gtk/gtkentry.h

index 4afa7247f5f20064603fa02eba16117716f5e7d0..9cde93e7bea2f42084283e27b697274a4f0b9e68 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2006-03-10  Michael Natterer  <mitch@gimp.org>
+
+       * gtk/gtkentry.[ch]: applied refactored patch from maemo-gtk that
+       replaces the INNER_BORDER define by an "inner-border" style
+       property of type GtkBorder. Additionally, add an "inner-border"
+       object property plus API which allows to override any theme
+       border, to allow pixel-perfect positioning of entries for inline
+       editing. Fixes bug #333922.
+
+       * gtk/gtk.symbols: add the new public functions.
+
 2006-03-09  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkcombobox.c (gtk_combo_box_class_init): Replace the
index 4afa7247f5f20064603fa02eba16117716f5e7d0..9cde93e7bea2f42084283e27b697274a4f0b9e68 100644 (file)
@@ -1,3 +1,14 @@
+2006-03-10  Michael Natterer  <mitch@gimp.org>
+
+       * gtk/gtkentry.[ch]: applied refactored patch from maemo-gtk that
+       replaces the INNER_BORDER define by an "inner-border" style
+       property of type GtkBorder. Additionally, add an "inner-border"
+       object property plus API which allows to override any theme
+       border, to allow pixel-perfect positioning of entries for inline
+       editing. Fixes bug #333922.
+
+       * gtk/gtk.symbols: add the new public functions.
+
 2006-03-09  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkcombobox.c (gtk_combo_box_class_init): Replace the
index 33058be4d7864ae70854c12fd9b36a3dab1b1f8e..32a2c4c96de3f2465910c4e52d161289ffe5b254 100644 (file)
@@ -1146,6 +1146,7 @@ gtk_entry_get_activates_default
 gtk_entry_get_alignment
 gtk_entry_get_completion
 gtk_entry_get_has_frame
+gtk_entry_get_inner_border
 gtk_entry_get_invisible_char
 gtk_entry_get_layout
 gtk_entry_get_layout_offsets
@@ -1168,6 +1169,7 @@ gtk_entry_set_activates_default
 gtk_entry_set_alignment
 gtk_entry_set_completion
 gtk_entry_set_has_frame
+gtk_entry_set_inner_border
 gtk_entry_set_invisible_char
 gtk_entry_set_max_length
 gtk_entry_set_text
index dfdb9e9a8d42a0610d49241459beb066e9c5d116..f1156d200f07be94bfb775d0c46eecff6d068f3c 100644 (file)
@@ -61,7 +61,6 @@
 
 #define MIN_ENTRY_WIDTH  150
 #define DRAW_TIMEOUT     20
-#define INNER_BORDER     2
 #define COMPLETION_TIMEOUT 300
 
 /* Initial size of buffer, in bytes */
@@ -70,6 +69,9 @@
 /* Maximum size of text buffer, in bytes */
 #define MAX_SIZE G_MAXUSHORT
 
+static const GtkBorder default_inner_border = { 2, 2, 2, 2 };
+static GQuark          quark_inner_border   = 0;
+
 typedef struct _GtkEntryPrivate GtkEntryPrivate;
 
 #define GTK_ENTRY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_ENTRY, GtkEntryPrivate))
@@ -102,6 +104,7 @@ enum {
   PROP_MAX_LENGTH,
   PROP_VISIBILITY,
   PROP_HAS_FRAME,
+  PROP_INNER_BORDER,
   PROP_INVISIBLE_CHAR,
   PROP_ACTIVATES_DEFAULT,
   PROP_WIDTH_CHARS,
@@ -124,14 +127,14 @@ static void   gtk_entry_class_init           (GtkEntryClass        *klass);
 static void   gtk_entry_editable_init        (GtkEditableClass     *iface);
 static void   gtk_entry_cell_editable_init   (GtkCellEditableIface *iface);
 static void   gtk_entry_init                 (GtkEntry         *entry);
-static void   gtk_entry_set_property (GObject         *object,
-                                     guint            prop_id,
-                                     const GValue    *value,
-                                     GParamSpec      *pspec);
-static void   gtk_entry_get_property (GObject         *object,
-                                     guint            prop_id,
-                                     GValue          *value,
-                                     GParamSpec      *pspec);
+static void   gtk_entry_set_property         (GObject          *object,
+                                              guint             prop_id,
+                                              const GValue     *value,
+                                              GParamSpec       *pspec);
+static void   gtk_entry_get_property         (GObject          *object,
+                                              guint             prop_id,
+                                              GValue           *value,
+                                              GParamSpec       *pspec);
 static void   gtk_entry_finalize             (GObject          *object);
 static void   gtk_entry_destroy              (GtkObject        *object);
 
@@ -330,6 +333,8 @@ static void         get_widget_window_size             (GtkEntry       *entry,
                                                        gint           *y,
                                                        gint           *width,
                                                        gint           *height);
+static void         get_inner_border                   (GtkEntry       *entry,
+                                                        GtkBorder      *border);
 
 /* Completion */
 static gint         gtk_entry_completion_timeout       (gpointer            data);
@@ -485,6 +490,8 @@ gtk_entry_class_init (GtkEntryClass *class)
   class->toggle_overwrite = gtk_entry_toggle_overwrite;
   class->activate = gtk_entry_real_activate;
   
+  quark_inner_border = g_quark_from_static_string ("gtk-entry-inner-border");
+
   g_object_class_install_property (gobject_class,
                                    PROP_CURSOR_POSITION,
                                    g_param_spec_int ("cursor-position",
@@ -538,6 +545,14 @@ gtk_entry_class_init (GtkEntryClass *class)
                                                          TRUE,
                                                         GTK_PARAM_READWRITE));
 
+  g_object_class_install_property (gobject_class,
+                                   PROP_INNER_BORDER,
+                                   g_param_spec_boxed ("inner-border",
+                                                       P_("Inner Border"),
+                                                       P_("Border between text and frame. Overrides the inner-border style propety"),
+                                                       GTK_TYPE_BORDER,
+                                                       GTK_PARAM_READWRITE));
+
   g_object_class_install_property (gobject_class,
                                    PROP_INVISIBLE_CHAR,
                                    g_param_spec_unichar ("invisible-char",
@@ -867,7 +882,21 @@ gtk_entry_class_init (GtkEntryClass *class)
   gtk_binding_entry_add_signal (binding_set, GDK_KP_Insert, 0,
                                "toggle_overwrite", 0);
 
-  gtk_settings_install_property (g_param_spec_boolean ("gtk-entry-select-on-focus",
+  /**
+   * GtkEntry:inner-border:
+   *
+   * Sets the text area's border between the text and the frame
+   *
+   * Since: 2.10
+   */
+  gtk_widget_class_install_style_property (widget_class,
+                                          g_param_spec_boxed ("inner-border",
+                                                               P_("Inner Border"),
+                                                               P_("Border between text and frame."),
+                                                               GTK_TYPE_BORDER,
+                                                               GTK_PARAM_READABLE));
+
+   gtk_settings_install_property (g_param_spec_boolean ("gtk-entry-select-on-focus",
                                                       P_("Select on focus"),
                                                       P_("Whether to select the contents of an entry when it is focused"),
                                                       TRUE,
@@ -944,6 +973,10 @@ gtk_entry_set_property (GObject         *object,
       gtk_entry_set_has_frame (entry, g_value_get_boolean (value));
       break;
 
+    case PROP_INNER_BORDER:
+      gtk_entry_set_inner_border (entry, g_value_get_boxed (value));
+      break;
+
     case PROP_INVISIBLE_CHAR:
       gtk_entry_set_invisible_char (entry, g_value_get_uint (value));
       break;
@@ -1004,6 +1037,9 @@ gtk_entry_get_property (GObject         *object,
     case PROP_HAS_FRAME:
       g_value_set_boolean (value, entry->has_frame);
       break;
+    case PROP_INNER_BORDER:
+      g_value_set_boxed (value, gtk_entry_get_inner_border (entry));
+      break;
     case PROP_INVISIBLE_CHAR:
       g_value_set_uint (value, entry->invisible_char);
       break;
@@ -1273,6 +1309,7 @@ gtk_entry_size_request (GtkWidget      *widget,
   GtkEntry *entry = GTK_ENTRY (widget);
   PangoFontMetrics *metrics;
   gint xborder, yborder;
+  GtkBorder inner_border;
   PangoContext *context;
   
   gtk_widget_ensure_style (widget);
@@ -1285,22 +1322,20 @@ gtk_entry_size_request (GtkWidget      *widget,
   entry->descent = pango_font_metrics_get_descent (metrics);
   
   _gtk_entry_get_borders (entry, &xborder, &yborder);
-  
-  xborder += INNER_BORDER;
-  yborder += INNER_BORDER;
-  
+  get_inner_border (entry, &inner_border);
+
   if (entry->width_chars < 0)
-    requisition->width = MIN_ENTRY_WIDTH + xborder * 2;
+    requisition->width = MIN_ENTRY_WIDTH + xborder * 2 + inner_border.left + inner_border.right;
   else
     {
       gint char_width = pango_font_metrics_get_approximate_char_width (metrics);
       gint digit_width = pango_font_metrics_get_approximate_digit_width (metrics);
       gint char_pixels = (MAX (char_width, digit_width) + PANGO_SCALE - 1) / PANGO_SCALE;
       
-      requisition->width = char_pixels * entry->width_chars + xborder * 2;
+      requisition->width = char_pixels * entry->width_chars + xborder * 2 + inner_border.left + inner_border.right;
     }
     
-  requisition->height = PANGO_PIXELS (entry->ascent + entry->descent) + yborder * 2;
+  requisition->height = PANGO_PIXELS (entry->ascent + entry->descent) + yborder * 2 + inner_border.top + inner_border.bottom;
 
   pango_font_metrics_unref (metrics);
 }
@@ -1368,6 +1403,32 @@ get_widget_window_size (GtkEntry *entry,
     }
 }
 
+static void
+get_inner_border (GtkEntry  *entry,
+                  GtkBorder *border)
+{
+  GtkBorder *tmp_border;
+
+  tmp_border = g_object_get_qdata (G_OBJECT (entry), quark_inner_border);
+
+  if (tmp_border)
+    {
+      *border = *tmp_border;
+      return;
+    }
+
+  gtk_widget_style_get (GTK_WIDGET (entry), "inner-border", &tmp_border, NULL);
+
+  if (tmp_border)
+    {
+      *border = *tmp_border;
+      g_free (tmp_border);
+      return;
+    }
+
+  *border = default_inner_border;
+}
+
 static void
 gtk_entry_size_allocate (GtkWidget     *widget,
                         GtkAllocation *allocation)
@@ -3151,15 +3212,17 @@ get_layout_position (GtkEntry *entry,
   PangoLayout *layout;
   PangoRectangle logical_rect;
   gint area_width, area_height;
+  GtkBorder inner_border;
   gint y_pos;
   PangoLayoutLine *line;
   
   layout = gtk_entry_ensure_layout (entry, TRUE);
 
-  get_text_area_size (entry, NULL, NULL, &area_width, &area_height);      
-      
-  area_height = PANGO_SCALE * (area_height - 2 * INNER_BORDER);
-  
+  get_text_area_size (entry, NULL, NULL, &area_width, &area_height);
+  get_inner_border (entry, &inner_border);
+
+  area_height = PANGO_SCALE * (area_height - inner_border.top - inner_border.bottom);
+
   line = pango_layout_get_lines (layout)->data;
   pango_layout_line_get_extents (line, NULL, &logical_rect);
   
@@ -3175,10 +3238,10 @@ get_layout_position (GtkEntry *entry,
   else if (y_pos + logical_rect.height > area_height)
     y_pos = area_height - logical_rect.height;
   
-  y_pos = INNER_BORDER + y_pos / PANGO_SCALE;
+  y_pos = inner_border.top + y_pos / PANGO_SCALE;
 
   if (x)
-    *x = INNER_BORDER - entry->scroll_offset;
+    *x = inner_border.left - entry->scroll_offset;
 
   if (y)
     *y = y_pos;
@@ -3215,6 +3278,7 @@ gtk_entry_draw_text (GtkEntry *entry)
          gint n_ranges, i;
           PangoRectangle logical_rect;
          GdkColor *selection_color, *text_color;
+          GtkBorder inner_border;
 
          pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
          gtk_entry_get_pixel_ranges (entry, &ranges, &n_ranges);
@@ -3230,9 +3294,11 @@ gtk_entry_draw_text (GtkEntry *entry)
              text_color = &widget->style->text [GTK_STATE_ACTIVE];
            }
 
+          get_inner_border (entry, &inner_border);
+
          for (i = 0; i < n_ranges; ++i)
            cairo_rectangle (cr,
-                            INNER_BORDER - entry->scroll_offset + ranges[2 * i],
+                            inner_border.left - entry->scroll_offset + ranges[2 * i],
                             y,
                             ranges[2 * i + 1],
                             logical_rect.height);
@@ -3286,7 +3352,8 @@ gtk_entry_draw_cursor (GtkEntry  *entry,
       GdkRectangle cursor_location;
       gboolean split_cursor;
 
-      gint xoffset = INNER_BORDER - entry->scroll_offset;
+      GtkBorder inner_border;
+      gint xoffset;
       gint strong_x, weak_x;
       gint text_area_height;
       PangoDirection dir1 = PANGO_DIRECTION_NEUTRAL;
@@ -3294,6 +3361,10 @@ gtk_entry_draw_cursor (GtkEntry  *entry,
       gint x1 = 0;
       gint x2 = 0;
 
+      get_inner_border (entry, &inner_border);
+
+      xoffset = inner_border.left - entry->scroll_offset;
+
       gdk_drawable_get_size (entry->text_area, NULL, &text_area_height);
       
       gtk_entry_get_cursor_locations (entry, type, &strong_x, &weak_x);
@@ -3323,9 +3394,9 @@ gtk_entry_draw_cursor (GtkEntry  *entry,
        }
 
       cursor_location.x = xoffset + x1;
-      cursor_location.y = INNER_BORDER;
+      cursor_location.y = inner_border.top;
       cursor_location.width = 0;
-      cursor_location.height = text_area_height - 2 * INNER_BORDER ;
+      cursor_location.height = text_area_height - inner_border.top - inner_border.bottom;
 
       draw_insertion_cursor (entry,
                             &cursor_location, TRUE, dir1,
@@ -3451,6 +3522,7 @@ gtk_entry_adjust_scroll (GtkEntry *entry)
   GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
   gint min_offset, max_offset;
   gint text_area_width, text_width;
+  GtkBorder inner_border;
   gint strong_x, weak_x;
   gint strong_xoffset, weak_xoffset;
   gfloat xalign;
@@ -3460,9 +3532,11 @@ gtk_entry_adjust_scroll (GtkEntry *entry)
 
   if (!GTK_WIDGET_REALIZED (entry))
     return;
-  
+
+  get_inner_border (entry, &inner_border);
+
   gdk_drawable_get_size (entry->text_area, &text_area_width, NULL);
-  text_area_width -= 2 * INNER_BORDER;
+  text_area_width -= inner_border.left + inner_border.right;
   if (text_area_width < 0)
     text_area_width = 0;
 
@@ -4315,6 +4389,58 @@ gtk_entry_get_has_frame (GtkEntry *entry)
   return entry->has_frame;
 }
 
+/**
+ * gtk_entry_set_inner_border:
+ * @entry: a #GtkEntry
+ * @border: a #GtkBorder, or %NULL
+ *
+ * Sets %entry's inner-border property to %border, or clears it if %NULL
+ * is passed. The inner-border is the area around the entry's text, but
+ * inside its frame.
+ *
+ * If set, this property overrides the inner-border style property.
+ * Overriding the style-provided border is useful when you want to do
+ * in-place editing of some text in a canvas or list widget, where
+ * pixel-exact positioning of the entry is important.
+ *
+ * Since: 2.10
+ **/
+void
+gtk_entry_set_inner_border (GtkEntry        *entry,
+                            const GtkBorder *border)
+{
+  g_return_if_fail (GTK_IS_ENTRY (entry));
+
+  gtk_widget_queue_resize (GTK_WIDGET (entry));
+
+  if (border)
+    g_object_set_qdata_full (G_OBJECT (entry), quark_inner_border,
+                             gtk_border_copy (border),
+                             (GDestroyNotify) gtk_border_free);
+  else
+    g_object_set_qdata (G_OBJECT (entry), quark_inner_border, NULL);
+
+  g_object_notify (G_OBJECT (entry), "inner-border");
+}
+
+/**
+ * gtk_entry_get_inner_border:
+ * @entry: a #GtkEntry
+ *
+ * This function returns the entry's inner-border property. See
+ * gtk_entry_set_inner_border() for more information.
+ *
+ * Return value: the entry's #GtkBorder, or %NULL if none was set.
+ *
+ * Since: 2.10
+ **/
+G_CONST_RETURN GtkBorder *
+gtk_entry_get_inner_border (GtkEntry *entry)
+{
+  g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
+
+  return g_object_get_qdata (G_OBJECT (entry), quark_inner_border);
+}
 
 /**
  * gtk_entry_get_layout:
@@ -4878,7 +5004,7 @@ gtk_entry_drag_data_received (GtkWidget        *widget,
   GtkEditable *editable = GTK_EDITABLE (widget);
   gchar *str;
 
-  str = gtk_selection_data_get_text (selection_data);
+  str = (gchar *) gtk_selection_data_get_text (selection_data);
 
   if (str && entry->editable)
     {
index cd9c6311a6df4d61564de1bdf948115a851eac46..18fca46e3f9ea6179b6b06788ec467e701a2f4a8 100644 (file)
@@ -152,6 +152,9 @@ gunichar   gtk_entry_get_invisible_char         (GtkEntry      *entry);
 void       gtk_entry_set_has_frame              (GtkEntry      *entry,
                                                  gboolean       setting);
 gboolean   gtk_entry_get_has_frame              (GtkEntry      *entry);
+void       gtk_entry_set_inner_border                (GtkEntry        *entry,
+                                                      const GtkBorder *border);
+G_CONST_RETURN GtkBorder* gtk_entry_get_inner_border (GtkEntry        *entry);
 /* text is truncated if needed */
 void       gtk_entry_set_max_length            (GtkEntry      *entry,
                                                 gint           max);